package com.kamistoat.ruoyi.ruoyimallproduct.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kamistoat.ruoyi.ruoyimallproduct.dao.CategoryDao;
import com.kamistoat.ruoyi.ruoyimallproduct.entity.CategoryEntity;
import com.kamistoat.ruoyi.ruoyimallproduct.service.CategoryService;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {
    /**
     * 获取商品菜单树型结构
     */
    @Override
    public List<CategoryEntity> listWithTree() {
        // 由于类继承了ServiceImpl<CategoryDao, CategoryEntity>，
        // 所以baseMapper就是CategoryDao
        // 当然如果不嫌麻烦，也可以在类头自动注入CategoryDao来使用
        // 查询条件null代表查询所有数据
        // Dao.selectList()可以按照条件进行批量查询，查询结果将会自动封装成List形式
        List<CategoryEntity> categoryEntityList = baseMapper.selectList(null);
        if (categoryEntityList.size() == 0) {
            return Collections.emptyList();
        } else {
            // 组装树形的父子结构
            // 首先找出所有的一级分类————其parent_cid为0，也就是没有父id
            // 因此使用.stream().filter(函数体)对所有分类进行筛选，找到ParentCid==0
            // stream编程中，.filter(()->{})可以看做是一个插件，它的作用就是对.前的list进行过滤
            // .filter()插件的存在不影响.map()的位置，.map()可以在.filter()的前面或后面，但是.filter()总是对它前面的list进行过滤
            List<CategoryEntity> level1Menus = categoryEntityList.stream().filter((categoryEntity) -> {
                // .filter()前是原始的list
                // .filter()的return值是true/false，如果返回true，则保留这一条数据，如果为false则删除这一条数据。
                return categoryEntity.getParentCid() == 0;
            }).map((menu) -> {
                // .map()跟在.filter()之后，此时经过.filter()得到的list中只有一级菜单分类，.map()是在这个一级菜单list上进行操作
                // 对这个list中的每一个一级菜单，继续寻找每个一级分类的子分类
                // 寻找子分类是一个递归方法，它会从当前这个第一级分类开始，一直向下找到每一级分类的子分类
                menu.setChildren(getChildren(menu, categoryEntityList));
                return menu;
            }).sorted((menu1, menu2) -> {
                // 此时经过.map()后得到的是某一级上的全部分类(实体类中的children保存下一级分类)。再将他们按照其自身的Sort值来进行排序
                // 由于在有些数据的sort列没有填数据，也就是null，不加处理会出错
                return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
            }).collect(Collectors.toList());

            return level1Menus;
        }
    }


    /**
     * 一个递归方法，用于从全体分类中寻找当前分类的子分类
     *
     * @param categoryEntity     当前的某一级分类
     * @param categoryEntityList 全部分类原始list
     * @return 当前某一级分类的子分类
     */
    public List<CategoryEntity> getChildren(CategoryEntity categoryEntity, List<CategoryEntity> categoryEntityList) {
        // 同样使用.stream().filter(函数体)对所有分类进行筛选，找到ParentCid==当前分类的id
        List<CategoryEntity> childrenMenus = categoryEntityList.stream().filter((categoryEntityF) -> {
            return categoryEntityF.getParentCid().equals(categoryEntity.getCatId());
            // 第一次执行到这里，找出了第一级分类的所有子分类
            // 之后递归每次执行到这里，都是在向下寻找子分类
        }).map((menu) -> {
            // 遍历刚刚找到的子分类，然后这里就是执行递归了
            // 将自身作为getChildren的输入变量，再去找自身的子分类
            menu.setChildren(getChildren(menu, categoryEntityList));
            return menu;
        }).sorted((menu1, menu2) -> {
            return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
        }).collect(Collectors.toList());

        return childrenMenus;
    }
}
